package ir.blocks;

import ir.Block;
import ir.CellUnit;
import ir.StructuralDefinition;

import java.util.LinkedList;
import java.util.List;

import run.Cell;
import run.Facet;

/**
 * A block representing contextualized facets:
 * 		(.a,.b)(MYCELL)(.c,.d)
 * @author Thomas Chau
 *
 */
public class UnitFacetBlk extends Block{

	UnitBlk core;
	FacetsBlk left;
	FacetsBlk right;
	
	Cell coreReal;
	
	public UnitFacetBlk() {}
	public void setUnit(UnitBlk b) {
		core = b;

	}
	
	public UnitFacetBlk(UnitBlk ub) {
		core = ub;
	}
	
	public void setLeft(FacetsBlk b) {
		// give left a link to this unit, contextualize the Facets to the Cell
		left = b;
		left.setOwner(core);
	}
	
	public void setRight(FacetsBlk b) {
		right = b;
		right.setOwner(core);
	}

	/**
	 * Contextualize the facets on the LEFT to the Cell (our Unit). Return them.
	 * 
	 * CASE: NONE -- will return ALL!!!!!!!
	 */
	@Override
	public List<Facet> getLeftFacets(
			StructuralDefinition d) throws Exception {
		
		// lazy instantiate.
		if (coreReal == null)
			coreReal = core.getUnit().genesis(d);

		// TODO: Tmp: disabled ->ADD-> defaulting behavior.
//		List<Facet> facets = coreReal.getInFacets();
		List<Facet> facets = coreReal.getFacets();
		
		if(left != null){
			boolean legal = false;
			for(String f: left.facetNames){
				for(Facet fac: facets){
					if(fac.getName().equals(f))
						legal = true;
				}
				if(!legal)
					throw new Exception("The facet " + f + " is not legal.");
				legal = false;
			}
		}
		List<Facet> selected = new LinkedList<Facet>();
		for (Facet f : facets) {
			if (left != null && left.contains(f.getName()))
				selected.add(f);	
		}
		// if the facets are unspecified, assume ALL FACETS ELIGIBLE FOR LEFT
		if (left == null) {
			selected = facets;
		}
		
		return selected;
	}


	/**
	 * Contextualize the facets on the RIGHT to the Cell (our Unit). Return them.
	 */
	@Override
	public List<Facet> getRightFacets(
			StructuralDefinition d) throws Exception{

		//	lazy instantiate.
		if (coreReal == null)
			coreReal = core.getUnit().genesis(d);
		
//		List<Facet> facets = coreReal.getOutFacets();
		List<Facet> facets = coreReal.getFacets();
		
		if(right != null){
			boolean legal = false;
			for(String f: right.facetNames){
				for(Facet fac: facets){
					if(fac.getName().equals(f))
						legal = true;
				}
				if(!legal)
					throw new Exception("The facet " + f + " is not legal.");
				legal = false;
			}
		}
		List<Facet> selected = new LinkedList<Facet>();
		for (Facet f : facets) {
			if (right != null && right.contains(f.getName()))
				selected.add(f);
		}
		// if the facets are unspecified, assume ALL FACETS ELIGIBLE FOR RIGHT
		if (right == null)
			selected = facets;
		
		
		return selected;
	}
	
	public String toString() {
		String s = "";
		if (left != null)
			s += "(" + left.toString() + ")";
		s += "(" + core.toString() + ")";
		if (right != null)
			s += "(" + right.toString() + ")";
		return s;
	}
	
	public CellUnit findInstance(String labelName) {
		try {
			if (core.getUnit().getLabel().equals(labelName))
				return core.getUnit();
			else return null;
		} catch (Exception e) {
			System.out.println("Failed trying to resolve instance of " + labelName);
		}
		return null;
	}
	
	public UnitFacetBlk clone() {
		UnitFacetBlk replace = new UnitFacetBlk();
		replace.setUnit(core.clone());
		
		if (left != null)
			replace.setLeft(left.clone());
		
		if (right != null)
			replace.setRight(right.clone());
		return replace;
	}
}
